#include "TCPServer.h"
#include <string.h>
const int TCPBUFFER=1024;
const int MAXCLIENTNUM=5;


TCPServer::TCPServer()
{
	m_bTcpInit = false;
	m_Socket = -1;
	m_bConnect = false;
	m_nPort=0;
	m_pIpAddr=NULL;
}

TCPServer::~TCPServer()
{
	closeTcpSocket();
}

//set listening port
bool TCPServer::setListenPort(int serPort)
{
	bool temp=false;
	do
	{
		if (serPort < 0)
		{
			printf("Error:serPort is err. serPort=%d\n",serPort);
			temp= false;
			break;
		}

		if (!m_bTcpInit)
		{
			if ((m_Socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
			{
				m_bTcpInit = false;
				printf("Error:build socket err\n");
				temp= false;
				break;
			}

			struct sockaddr_in addrTcpSrv;
#ifdef unix
			bzero(&addrTcpSrv,sizeof(addrTcpSrv));
#endif
			addrTcpSrv.sin_addr.s_addr = INADDR_ANY;
			addrTcpSrv.sin_family = AF_INET;
			addrTcpSrv.sin_port= htons(serPort);

			int nRet = bind(m_Socket, (struct sockaddr*)&addrTcpSrv, sizeof(struct sockaddr));
			if (nRet != 0)
			{
				printf("Error: bind  failed!\n");
				temp= false;
				break;
			}
			if (listen(m_Socket, MAXCLIENTNUM) != 0)
			{
				printf("Error: listening failed!\n");
				temp= false;
				break;
			}
			m_bTcpInit = true;
			printf("server is listening:%d\n",serPort);
			temp= true;
			break;
		}
		printf("Error: m_bTcpInit has init before!\n");
		temp= false;
		break;
	}while(false);
	return temp;
}

//accept
int TCPServer::setAccept(TCPServer *pSocket, struct sockaddr *clientAddr, int timeOut)
{
	struct timeval tv;
	tv.tv_sec = timeOut/1000;
	tv.tv_usec = (timeOut%1000)*1000;

	fd_set rd;
	FD_ZERO(&rd);
	FD_SET(m_Socket,&rd);

	switch (select(m_Socket+1, &rd, 0, 0, &tv)) 
	{  
	case -1:  
		printf("Error:select is erro..\n");
		return -1;

	case 0:  
		//printf("Error:select timeout ...\n");
		return -1;

	default:  
		if (FD_ISSET(m_Socket,&rd)) 
		{  
#ifdef _WIN32
			int addrLen=0;
#else
			socklen_t addrLen=0;
#endif
			addrLen = sizeof(struct sockaddr);

			int socketfd = accept(m_Socket,clientAddr, &addrLen);

			if ( socketfd <=0)
			{
				printf("accept failed...socketfd\n",socketfd);
				return -1;
			}
			else
			{
				pSocket->initSocketfd(socketfd);
				pSocket->initm_bConnect(true);
				return socketfd;
			}
		}
		else
		{
			printf("Error:FD_ISSET erro ...\n");
			return -1;
		}
	}  	
}


//send data
int TCPServer::sendData(const char *szContent,int nLength,int nTimeOut)
{
	int nSend = 0;
	do
	{
		if(!szContent || nLength<=0 || nTimeOut<0)
		{
			printf("Error: !szContent || nLength<=0 || nTimeOut\n");
			nSend= -1;
			break;
		}

		if(!m_bConnect)
		{
			printf("Error: haven connected,m_bConnect is false!\n");
			nSend= -1;
			break;
		}
#ifdef _WIN32
		int tvOut=nTimeOut;
#else
		struct timeval tvOut;
		tvOut.tv_sec = nTimeOut/1000;
		tvOut.tv_usec = (nTimeOut%1000)*1000;
#endif

		int retSet=setsockopt(m_Socket,SOL_SOCKET,SO_SNDTIMEO,(const char*)&tvOut,sizeof(tvOut)); 
		if(0 != retSet)
		{
			printf("setSocketOpt failed:%s\n",strerror(errno));
		}

		nSend=send(m_Socket,szContent,nLength,0);
		if (nSend == -1)
		{
			printf("TCP Send Failed!\n");
			nSend= -1;
			break;
		}
	}while(false);
	return nSend;
}

//recv
int TCPServer::receive(char *szBuf, int nBufLength, int nTimeOut)
{
	int nRecv = 0;
	do
	{
		if(!szBuf || nBufLength<=0 || nTimeOut<0)
		{
			printf("Error: !szBuf || nBufLength<=0 || nTimeOut<0\n");
			nRecv= -1;
			break;
		}
		if(!m_bConnect)
		{
			printf("TCP Receive Failed,Not Connected.\n");
			nRecv= -1;
			break;
		}

		// set timeout
#ifdef _WIN32
		int tvOut=nTimeOut;
#else
		struct timeval tvOut;
		tvOut.tv_sec = nTimeOut/1000;
		tvOut.tv_usec = (nTimeOut%1000)*1000;
#endif
		int retSet=setsockopt(m_Socket, SOL_SOCKET,SO_RCVTIMEO,(const char*)&tvOut,sizeof(tvOut)); 
		if(0 != retSet)
		{
			printf("setSocketOpt failed:%s\n",strerror(errno));
		}
		nRecv = recv(m_Socket, szBuf,nBufLength,0);
	}while(false);
	return nRecv;
}

//recv all data to strRecv
int TCPServer::receiveAllData(char *bufRecv,int nTimeOut)
{
	int nTotal=0;
	char recv_buff[TCPBUFFER+1] = { 0 };
	int	 nCount=0;
	int tempCount=0;
	do
	{
		memset(recv_buff,0,sizeof(char)*(TCPBUFFER+1));
		nCount=receive(recv_buff, sizeof(char)*TCPBUFFER, nTimeOut);
		if(nCount>0)
		{
			nTotal+=nCount;
			memcpy(bufRecv+tempCount,recv_buff,sizeof(recv_buff));
			tempCount+=nCount;
		}
	}while(nCount>0);
	return nTotal;
}


//close
void TCPServer::closeTcpSocket()
{
	if(m_bConnect)
	{
#ifdef _WIN32
		closesocket(m_Socket);
#else
		close(m_Socket);
#endif
		m_bConnect = false;
		delete m_pIpAddr;
	}
}

void TCPServer::initSocketfd(int socketfd)
{
	m_Socket = socketfd;
}

int TCPServer::getSocketfd()
{
	return m_Socket;
}


void TCPServer::initm_bConnect(bool bConnect)
{
	m_bConnect = bConnect;
}

int TCPServer::getm_bConnect()
{
	return m_bConnect;
}

//set ip
void TCPServer::setIpAdd(char *tempIp)
{
	if (NULL==tempIp)
	{
		m_pIpAddr = new char[1];
		*m_pIpAddr='\0';
	}
	else
	{
		int len=strlen(tempIp);
		m_pIpAddr = new char[len+1];
		strcpy(m_pIpAddr,tempIp);
	}
}

//get ip
char* TCPServer::socketIP()
{
	return m_pIpAddr;
}

//set client's port
void TCPServer::setPort(int tempPort)
{
	m_nPort=tempPort;
}

//get client's port
int TCPServer::socketPort()
{
	return m_nPort;
}
